package me.ingxin.android.sysbar

import android.view.View
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsAnimationCompat
import androidx.core.view.WindowInsetsCompat

/**
 * Created by ingxin on 2022/5/21
 */
class IMEAnimationCompat(
    private val view: View,
    @DispatchMode dispatchMode: Int,
    private val callback: IMEAnimationCallback
) : WindowInsetsAnimationCompat.Callback(dispatchMode) {

    /**本轮触发回调时输入法状态*/
    private var status = STATUS_NONE

    /**软键盘顶部距离window底部的距离*/
    private var imeTop = 0

    /**输入法自身调节高度时之前的距离*/
    private var lastImeTop = 0

    /**处于弹出或者收起过程中*/
    var inProgress = false
        private set

    override fun onProgress(
        insetsCompat: WindowInsetsCompat,
        runningAnimations: MutableList<WindowInsetsAnimationCompat>
    ): WindowInsetsCompat {
        val imeAnimation = runningAnimations.find {
            it.typeMask and WindowInsetsCompat.Type.ime() != 0
        } ?: return insetsCompat

        when (status) {

            //显示
            STATUS_SHOW -> {
                if (lastImeTop != 0 && imeTop != lastImeTop) {
                    val top =
                        lastImeTop + (imeTop - lastImeTop) * imeAnimation.interpolatedFraction
                    callback.onProgress(top.toInt())
                } else {
                    val top = imeTop * imeAnimation.interpolatedFraction
                    callback.onProgress(top.toInt())
                }
            }

            //收起
            STATUS_DISMISS -> {
                val top = imeTop * (1 - imeAnimation.interpolatedFraction)
                callback.onProgress(top.toInt())
            }

            else -> return insetsCompat
        }
        return insetsCompat
    }

    override fun onStart(
        animation: WindowInsetsAnimationCompat,
        bounds: WindowInsetsAnimationCompat.BoundsCompat
    ): WindowInsetsAnimationCompat.BoundsCompat {

        inProgress = true

        val insets = ViewCompat.getRootWindowInsets(view)
        //获取本次完成后软键盘顶端距离window底部距离
        val h = insets?.getInsets(WindowInsetsCompat.Type.ime())?.bottom ?: 0
        val isVisible = insets?.isVisible(WindowInsetsCompat.Type.ime()) ?: false

        status = if (isVisible) {
            imeTop = h
            STATUS_SHOW
        } else {
            STATUS_DISMISS
        }
        return super.onStart(animation, bounds)
    }

    override fun onEnd(animation: WindowInsetsAnimationCompat) {
        lastImeTop = if (status == STATUS_SHOW) {
            imeTop
        } else {
            0
        }

        if (status == STATUS_DISMISS) {
            imeTop = 0
            status = STATUS_NONE
            //追加一个状态，防止异常结束
            callback.onProgress(0)
        }

        inProgress = false

    }

    fun isStarted(): Boolean {
        return status == STATUS_SHOW
    }

    /**
     * 在软键盘显示状态下调整键盘高度
     */
    internal fun adjustOnShow(top: Int) {
        //高度一致认定为无效变化
        if (imeTop == top) {
            return
        }
        imeTop = top
        callback.onProgress(imeTop)
    }

    companion object {

        /**输入法未初始化状态*/
        const val STATUS_NONE = 1

        /**输入法显示状态*/
        const val STATUS_SHOW = 3

        /**输入法收起状态*/
        const val STATUS_DISMISS = 4
    }

}